package dataStructure.tree;

import java.util.Arrays;

/**
 * @author lhn
 * @date 2024-09-04 18:49
 */

public class HeapSortDemo {
    public static void main(String[] args) {
        int[] arr = {4, 6, 8, 5, 9};
        sort(arr);
    }

    public static void sort(int[] arr) {
        int n = arr.length;

        //1.从最后一个非叶子节点开始，向前遍历到根节点，对每个节点调用adjustHeap函数，
        //以确保整个数组（或更准确地说是前n个元素，其中n是数组的长度）被构建成一个大顶堆。
        //调整以i为根节点的的子树满足大顶堆的性质
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            adjustHeap(arr, i, n);
        }
        System.out.println("构建的大顶堆：" + Arrays.toString(arr));

        //2.循环将堆顶元素与末尾元素交换，然后n - 1
        //3.在重新调整堆，这样循环就完成了堆排序
        for (int i = n - 1; i > 0; i--) {
            //将堆顶元素与末尾元素交换
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            //重新对堆进行调整
            adjustHeap(arr, 0, i);  //从根节点开始，确保剩余的i个元素满足大顶堆的性质。
            System.out.println(Arrays.toString(arr));
        }
    }

    //
    /**
    * 将一个数组调整成一个大顶堆
     * @param arr 待调整的数组
     * @param i 非叶子节点在数组中的索引
     * @param length 待调整的数组的长度
    */
    public static void  adjustHeap(int[] arr, int i, int length) {
        int temp = arr[i];  //保存要调整的节点的值
        //i的左子节点k = 2*i+1，右子节点k = 2*i+2
        //每一调整k的值，都与左右子节点比较，取大值与temp比较，取大值与temp交换
        for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
            //判断左子节点是否小于右子节点
            if (k + 1 < length && arr[k] < arr[k + 1]) {
                k++;    //k指向右子节点
            }
            //如果要调整的节点小于其子节点，则交换
            if (temp < arr[k]) {
                arr[i] = arr[k];
                i = k;  //继续调整i，即继续比较k下面的子节点
            } else {
                break;
            }
        }
        //当for 循环结束后，已经得到 i 为父节点的树的最大值，放在 i 的位置
        arr[i] = temp;  //将temp放到调整后的位置
    }
}
